package com.itheima.sync.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.itheima.goods.pojo.Goods;
import com.itheima.goods.pojo.GoodsInfo;
import com.itheima.sync.mapper.DataSyncDao;
import com.itheima.sync.service.DataSyncService;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.CreateIndexRequest;
import org.elasticsearch.client.indices.GetIndexRequest;
import org.elasticsearch.common.xcontent.XContentType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.util.List;
import java.util.Map;

/**
 * @author wang
 * @description
 * @date 2021/7/31 9:34
 */
@Service("dataSyncService")
public class DataSyncServiceImpl extends ServiceImpl<DataSyncDao, Goods> implements DataSyncService {
    private final static String INDEX_NAME = "goodsinfo";

    @Autowired
    @Qualifier("restHighLevelClient")
    private RestHighLevelClient client;

    @Override
    @Transactional(propagation = Propagation.SUPPORTS,readOnly = true)
    public void importAll() {
        //1.查询所有上架商品数据
        List<Goods> goodsList = this.list();
        //2.判断 goodsinfo 索引库是否存在
        if (isExist()) {
            //存在--> 删除该索引库
            deleteIndex();
        }
        //3.创建 goodsinfo 索引库 (脚本上面找)
        createIndex();
        //4.使用批量导入API导入全部商品数据
        if (goodsList != null && !goodsList.isEmpty()) {
            importAll(goodsList);
        }
    }

    /**
     * 判断索引库是否存在
     *
     * @return
     */
    private boolean isExist() {
        GetIndexRequest request = new GetIndexRequest(INDEX_NAME);
        try {
            return client.indices().exists(request, RequestOptions.DEFAULT);
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 删除索引库
     */
    private void deleteIndex() {
        DeleteIndexRequest request = new DeleteIndexRequest(INDEX_NAME);
        try {
            client.indices().delete(request, RequestOptions.DEFAULT);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 创建索引库
     */
    private void createIndex() {
        CreateIndexRequest request = new CreateIndexRequest(INDEX_NAME);
        try {
            request.mapping("{" +
                    "\"properties\": {" +
                    "\"id\": {" +
                    "\"type\": \"integer\"" +
                    "}," +
                    "\"image\": {" +
                    "\"index\": false," +
                    "\"type\": \"keyword\"" +
                    "}," +
                    "\"brandId\": {" +
                    "\"type\": \"integer\"" +
                    "}," +
                    "\"categoryId\": {" +
                    "\"type\": \"integer\"" +
                    "}," +
                    "\"brandName\": {" +
                    "\"type\": \"keyword\"" +
                    "}," +
                    "\"categoryName\": {" +
                    "\"type\": \"keyword\"" +
                    "}," +
                    "\"num\": {" +
                    "\"type\": \"integer\"" +
                    "}," +
                    "\"specMap\": {" +
                    "\"type\": \"object\"" +
                    "}," +
                    "\"updateTime\": {" +
                    "\"type\": \"date\"" +
                    "}," +
                    "\"spec\": {" +
                    "\"type\": \"keyword\"" +
                    "}," +
                    "\"createTime\": {" +
                    "\"type\": \"date\"" +
                    "}," +
                    "\"price\": {" +
                    "\"type\": \"integer\"" +
                    "}," +
                    "\"name\": {" +
                    "\"analyzer\": \"ik_max_word\"," +
                    "\"type\": \"text\"" +
                    "}," +
                    "\"status\": {" +
                    "\"type\": \"keyword\"" +
                    "}" +
                    "}" +
                    "}", XContentType.JSON);
            client.indices().create(request, RequestOptions.DEFAULT);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 导入所有数据
     *
     * @param goodsList mysql中数据
     */
    private void importAll(List<Goods> goodsList) {
        BulkRequest request = new BulkRequest(INDEX_NAME);
        for (Goods goods : goodsList) {
            GoodsInfo goodsInfo = convertGoods2GoodsInfo(goods);
            request.add(new IndexRequest(INDEX_NAME).id(goodsInfo.getId() + "")
                    .source(JSON.toJSONString(goodsInfo),XContentType.JSON));
        }
        try {
            client.bulk(request,RequestOptions.DEFAULT);
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("批量添加索引失败");
        }
    }

    private GoodsInfo convertGoods2GoodsInfo(Goods goods) {
        //goods与goodsInfo中属性名相同的自动封装
        String goodsStr = JSON.toJSONString(goods);
        GoodsInfo goodsInfo = JSON.parseObject(goodsStr, GoodsInfo.class);
        //组装品牌及名称
        goodsInfo.setBrandName(goods.getBrand());
        //组装分类数据
        goodsInfo.setCategoryName(goods.getCategory());
        //组装
        String spec = goods.getSpec();
        Map sepcMap = JSON.parseObject(spec, Map.class);
        goodsInfo.setSpecMap(sepcMap);
        goodsInfo.setCreateTime(goods.getCreatetime());
        goodsInfo.setUpdateTime(goods.getUpdatetime());
        return goodsInfo;
    }
}
